#include "droppable_tile.h"

CDroppableTile::CDroppableTile(float fX, float fY, float fZ, 
        float fEndX, float fEndY, float fEndZ, const CTimer &endTime)
    : CMovableEntity("droppable_tile", ENT_TILE_DROPPABLE, fX, fY, fZ),
    m_fEndX(fEndX),
    m_fEndY(fEndY),
    m_fEndZ(fEndZ),
    m_StartTime(),
    m_EndTime(endTime),
    m_LastAnimatedTime()
{
    /**
     * Constructor, ensure that we load the textures and set the tile at a 
     * given height.
     *
     * @param float fX The starting X position of the tile.
     * @param float fY The starting Y position of the tile.
     * @param float fZ The starting Z position of the tile.
     * @param float fEndX The ending X position of the tile.
     * @param float fEndY The ending Y position of the tile.
     * @param float fEndZ The ending Z position of the tile.
     * @param CTimer &endTimer The time the tile will fall into the place.
     */

    CMesh *pMesh(CMeshContainer::getInstance()->getMesh("tile"));
    if (pMesh == nullptr)
    {
        pMesh = CMeshContainer::getInstance()->addMesh("tile");
        pMesh->loadMesh(CDeviceManager::getInstance()->getDevice(), 
            "models/game/tile.x");
    }

    setDisplayable(CDisplayableContainer::getInstance()->createDisplayable(
        pMesh));

    CTextureContainer *pTextures(CTextureContainer::getInstance());
    CTexture *pTexture(pTextures->getTexture("textures/tiles/concrete.png"));
    if (pTexture == nullptr)
    {
        // Texture doesn't exist
        pTexture = pTextures->addTexture("textures/tiles/concrete.png", 
            "textures/tiles/concrete.png", 
            CDeviceManager::getInstance()->getDevice());
    }

    for (int nSubset(0); nSubset < 6; ++nSubset)
    {
        getDisplayable()->setTexture(pTexture, nSubset);
    }
}

void CDroppableTile::tick()
{
    /**
     * Executed every tick, ensure that we move the object closer to the 
     * destination relative to the time difference.
     */    

    double dTimeLeft(m_LastAnimatedTime.getTimeDifference(m_EndTime));

    if (dTimeLeft > 0)
    {
        // Calculate the total time the animation will last
        

        // Calculate the amount of time since last tick
        double dTimer(m_LastAnimatedTime.getTimeDifference());

        // Calculate how far to move the projectile.
        double dXChange((m_fEndX - getX()) / dTimeLeft * dTimer);
        double dYChange((m_fEndY - getY()) / dTimeLeft * dTimer);
        double dZChange((m_fEndZ - getZ()) / dTimeLeft * dTimer);

        // Update the position
        setX(getX() + static_cast<float>(dXChange));
        setY(getY() + static_cast<float>(dYChange));
        setZ(getZ() + static_cast<float>(dZChange));

        // Update the last animated time
        m_LastAnimatedTime.setTime();
    }
    else
    {
        setX(m_fEndX);
        setY(m_fEndY);
        setZ(m_fEndZ);

        int nHeight(0), nWidth(0), nDepth(0);

        CMap *pMap(CMapContainer::getInstance()->getCurrentMap());
        if (pMap != nullptr)
        {
            pMap->getTilePositionFromCoord(nHeight, nWidth, nDepth,
                m_fEndX, m_fEndY, m_fEndZ, 0);
            if (pMap->isValidTile(nHeight, nWidth, nDepth))
            {
                CTile *pTile(pMap->getTile(nHeight, nWidth, nDepth));
                CTile *pNewTile(new CConcreteTile(nHeight, nWidth, nDepth));

                CEntityContainer *pEntities(CEntityContainer::getInstance());

                if (pTile->isEntityInBlock(ENT_PLAYER))
                {
                    vector<CEntity*> arrPlayers(
                        pEntities->getEntityList(ENT_PLAYER));
                    for (vector<CEntity*>::iterator pEnt(arrPlayers.begin());
                         pEnt != arrPlayers.end(); ++pEnt)
                    {
                        CPlayer *pPlayer(dynamic_cast<CPlayer*>(*pEnt));
                        
                        int nPlayerHeight(0), nPlayerWidth(0), nPlayerDepth(0);

                        pMap->getTilePositionFromCoord(nPlayerHeight,
                            nPlayerWidth, nPlayerDepth, pPlayer->getX(),
                            pPlayer->getY(), pPlayer->getZ(), 0);
                        if (! pMap->isValidTile(nPlayerHeight, nPlayerWidth,
                            nPlayerDepth))
                        {
                            continue;
                        }

                        if (nPlayerHeight != nHeight || nPlayerWidth != nWidth
                            || nPlayerDepth != nDepth)
                        {
                            continue;
                        }

                        pPlayer->kill();
                    }
                }

                CSound *pSound(CSoundManager::getInstance()->addSound(
                    "solid_block_drop.ogg"));
                pSound->setVolume(0.5f);
                FMOD::Channel *pNewChannel(nullptr);
                pSound->createNewChannel(&pNewChannel);
                pNewChannel->setPaused(false);

                pMap->setTile(nHeight, nWidth, nDepth, pNewTile);

                pEntities->removeEntity(this);
            }
        }
    }
}